#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <string.h>

#define STANDALONE
#define DEFAULT_SIZE 256
#define LINE_MAX_SIZE 6 // 一行最多6个指令
// 指令最多的是mla指令，有一个操作码和四个操作数，本应该是五个，但是考虑到label，加在一起最多允许6个

typedef unsigned char byte;

typedef struct
{
    char *key; // malloc 动态申请内存，记得free
    int value;
} Map; // malloc 动态申请内存，记得free

typedef enum
{
    MOV,
    ADD,
    SUB,
    MUL,
    MLA,
    CMP,
    B,
    BEQ,
    BNE,
    BLT,
    BGT,
    BL,
    NOP,
    PUSH,
    POP,
    SWI,
    INSTRUCTION_SIZE
} Instructions;

typedef struct
{
    char *name; // 指令名称
    int instruction; // 指令字节码
    byte length; // 操作数长度，不包括操作码本身1的长度
} Instruction;

static Instruction instruction_mapping[] = { // 指令字符串到指令数字编号映射
    {"mov", MOV, 2},
    {"add", ADD, 3},
    {"sub", SUB, 3},
    {"mul", MUL, 3},
    {"mla", MLA, 4},
    {"cmp", CMP, 2},
    {"b", B, 1},
    {"beq", BEQ, 1},
    {"bne", BNE, 1},
    {"blt", BLT, 1},
    {"bgt", BGT, 1},
    {"bl", BL, 2},
    {"nop", NOP, 0},
    {"push", PUSH, 1},
    {"pop", POP, 1},
    {"swi", SWI, 1}};

typedef struct
{
    char *instructions[DEFAULT_SIZE]; // 存放字节码指令
    Map *maps[DEFAULT_SIZE]; // 存放label地址字典
    size_t map_index; // 当前字典计数
    int instruction_count; // 指令个数
    int instruction_index; // 当前指令索引
    bool is_halt;          // 虚拟机状态
} vmState;

void parserLabelAddress(vmState *vm);
void parser(vmState *vm, char *instr, Instruction *result);
void parserLine(vmState *vm, char *instr);
int getInstruction(vmState *vm, Instruction *result);